#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>

#define PORT 8888
#define SERVER_IP "192.168.152.130"
#define BUFFER_SIZE 128

//信号处理函数
void sig_func(int signum){
    wait(NULL); //处理SIGUSR1信号，避免僵尸进程
}

int main(int argc, char const *argv[])
{
    //创建套接字与服务器配置
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        perror("socket创建失败");
        return -1;
    }
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    socklen_t server_addr_len = sizeof(server_addr);

    //绑定、监听、信号注册
    if( bind(sockfd, (struct sockaddr *)&server_addr, server_addr_len) == -1){
        perror("绑定失败：");
        close(sockfd);
        return -1;
    }
    if( listen(sockfd, 5) == -1){
        perror("监听失败：");
        close(sockfd);
        return -1;
    }

    struct sockaddr_in client_addr;
    socklen_t client_addr_len = sizeof(client_addr);
    int acceptfd = 0;
    pid_t pid = 0;
    int ret = 0;

    signal(SIGUSR1, sig_func); //注册信号处理函数

    //主循环：接受连接并且创建子进程
    while(1){
        acceptfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_addr_len);
        if(acceptfd == -1){
            perror("接受连接失败：");
            close(sockfd);
        }
        pid = fork();
        if(pid == -1){
            perror("创建子进程失败：");
            close(acceptfd);
            break;
        }else if(pid == 0){
            //处理客户端通信
            char buf[BUFFER_SIZE] = {0};
            int nbytes = 0;
            printf("客户端【%s：%d】连接到服务器\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

            //接收数据
            nbytes = recv(acceptfd, buf, BUFFER_SIZE, 0);
            if(nbytes == -1){
                perror("接收失败：");
            }else if(nbytes == 0){
                printf("客户端【%s：%d】断开连接\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                break;
            }
            printf("客户端【%s：%d】发送的数据：%s\n",inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), buf);
            strcat(buf, " 来自服务端");
            //回显
            if(send(acceptfd, buf, BUFFER_SIZE, 0) == -1){
                perror("发送失败：");
            }
            close(acceptfd);
            kill(getpid(), SIGUSR1); //向父进程发送信号，避免僵尸进程
            exit(0);
        }else if(pid > 0){
            close(acceptfd);
        }   
    }

    close(sockfd);
    return 0;
}
